package com.sunwhite.herostore.cmdhandler;

import com.google.protobuf.GeneratedMessageV3;
import com.sunwhite.herostore.util.PackageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public final class CmdHandlerFactory {
    /**
     * 日志对象
     */
    private final static Logger log= LoggerFactory.getLogger(CmdHandlerFactory.class);

    private static Map<Class<?>, CmdHandler<? extends GeneratedMessageV3>> CMD_HADLER = new HashMap<>();

    /**
     * 方法不能继承和不能实例化
     */
    private CmdHandlerFactory() {
    }

    /**
     * 初始化消息处理器到map中
     */
    public static void init() {
        log.info("初始化消息处理器：");
        Set<Class<?>> classes = PackageUtil.listSubClazz(CmdHandlerFactory.class.getPackage().getName(), false, CmdHandler.class);
        for (Class<?> clazz : classes) {
            //判断是否是抽象类
            if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
                continue;
            }
            //获取类的所有的方法
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                //获取方法名称
                if (!method.getName().equalsIgnoreCase("handle")) {
                    continue;
                }
                //获取方法的参数类型。参数可能是多个所以是数组
                Class<?>[] parameterTypes = method.getParameterTypes();
                for (Class<?> parameterType : parameterTypes) {
                    //判断方法中参数是否是消息子类，并不属于消息父类，是的话加入map,因为一个消息器只能处理一种类型的消息，所以直接跳出参数循环
                    if (GeneratedMessageV3.class.isAssignableFrom(parameterType) && parameterType != GeneratedMessageV3.class) {
                        try {
                            Object newInstance = clazz.newInstance();
                            CMD_HADLER.put(parameterType, (CmdHandler) newInstance);
                            log.info("消息处理器：{}<==>{}",parameterType,newInstance.getClass().getSimpleName());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                }
            }
        }
    }

    /**
     * 返回一个适合处理消息的处理器
     *
     * @param tClass
     * @param <?>
     * @return
     */
    public static CmdHandler<? extends GeneratedMessageV3> create(Class<?> tClass) {
        if (tClass == null) {
            return null;
        }
        return CMD_HADLER.get(tClass);
    }


}
